package edu.kit.csl.cratylus.extraction.elki;

import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractPrimitiveDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.IntegerDistance;
import edu.kit.csl.cratylus.datatypes.Candidate;
import edu.kit.csl.cratylus.extraction.LevenshteinUtils;

/**
 * We provide ELKI a customized distance function in order to deal with
 * phoneme sequences (i.e. strings containing blank separated phonemes). The
 * implemented distance metric is the (integer) Levenshtein distance. The 
 * implementation itself is taken from Wikipedia.
 * 
 * @see LevenshteinUtils
 */
public class LevenshteinDistanceFunction extends
		AbstractPrimitiveDistanceFunction<ElkiCandidate, IntegerDistance> {

	/**
	 * Only accepts {@link ElkiCandidate} instances.
	 * {@inheritDoc}
	 */
	@Override
	public SimpleTypeInformation<? super ElkiCandidate> 
				getInputTypeRestriction() {
		return new SimpleTypeInformation<ElkiCandidate>(ElkiCandidate.class);
	}

	/**
	 * Calculates the Levenshtein distance between two phoneme sequences using
	 * dynamic programming. If both candidates are from the same sentence pair,
	 * but on another position, return 1000.
	 * 
	 * @param o1 first phoneme sequence
	 * @param o2 second phoneme sequence to compare with the {@code o1}
	 * @return the Levenshtein distance between {@code o1} and {@code o2}
	 * @throws NullPointerException if one of the arguments or their content
	 * 				is null
	 * @see LevenshteinUtils#distance(String[], String[])
	 */
	@Override
	public IntegerDistance distance(ElkiCandidate o1, ElkiCandidate o2) {
		Candidate c1 = o1.getValue(0);
		Candidate c2 = o2.getValue(0);
		/*if (c1.getWord().getRelatedWord() 
				== c2.getWord().getRelatedWord()) {
			return new IntegerDistance(c1.getPosition() != c2.getPosition() ?
					1000 : 0);
		}*/
		return new IntegerDistance(LevenshteinUtils.distance(
				c1.getWord().getContent().split(" "),
				c2.getWord().getContent().split(" ")));
	}

	@Override
	public IntegerDistance getDistanceFactory() {
		return IntegerDistance.FACTORY;
	}
}
